package smartgrid;

import SuppliersBeans.EDPbeanLocal;
import SuppliersBeans.ENDESAbeanLocal;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Stateless;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.hibernate.criterion.Restrictions;
import org.orm.PersistentException;
import smartgrid.exceptions.ContractAlreadyExistsException;
import smartgrid.exceptions.FacebookAccountNotExistException;
import smartgrid.exceptions.InvalidContractNifException;
import smartgrid.exceptions.InvalidContractNumberException;

@Stateless
public class ContractsManager implements Contracts {

    /**
     * 
     * @return Contract List of a Facebook Account
     */
    @Override
    public List<Contract> getContracts(FaceBookAccount fb) {
        ContractSetCollection cs;
        cs = fb.contract_role;

        return Arrays.asList(cs.toArray());
    }

    public List<Contract> getContracts() {
        Contract[] cs = Contract.listContractByQuery(null, null);

        return Arrays.asList(cs);
    }

    /**
     * 
     * @param id do contrato, ou seja, chave primaria
     * @return retorna um contrato
     */
    @Override
    public Contract getContract(int id) {
        Contract c = smartgrid.Contract.getContractByORMID(id);
        return c;
    }

    /**
     * 
     * @param Numero do contrato (nao o numero da chave primaria)
     * @return retorna um contrato
     */
    @Override
    public Contract getContractByNumber(String number) {
        try {
            smartgrid.ContractCriteria crit = new ContractCriteria();
            crit.add(Restrictions.eq("Number", number));
            Contract c = smartgrid.Contract.loadContractByCriteria(crit);
            return c;
        } catch (PersistentException ex) {
            Logger.getLogger(ContractsManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    /**
     * Inserts one new Contract
     * 
     * @param contractNumber Number of the Contract
     * @param clientName Client's name
     * @param clientNif Client's NIF number
     * @param supplierID Supplier's DB id
     * @param tariffID Tariff's DB id
     * @return if success: true
     */
    @Override
    public Boolean insertContract(String contractNumber, String clientName, String clientNif, Integer supplierID, Integer tariffID, String morada) {
        try {
            smartgrid.ContractCriteria crit = new ContractCriteria();
            crit.add(Restrictions.eq("Number", contractNumber));
            crit.add(Restrictions.eq("supplier_role.id", supplierID));
            smartgrid.Contract contract = smartgrid.Contract.loadContractByCriteria(crit);

            smartgrid.TariffCriteria tarifCrit = new TariffCriteria();
            tarifCrit.add(Restrictions.eq("ID", tariffID));
            smartgrid.Tariff tariff = smartgrid.Tariff.loadTariffByCriteria(tarifCrit);

            if (tariff.getSupplier_Tariffs_role().getID() == supplierID) {
                if (contract == null) {
                    smartgrid.ContractProcessor contractProcess = new smartgrid.ContractProcessor();
                    contractProcess.setClientName(clientName);
                    contractProcess.setClientNif(clientNif);
                    contractProcess.setNumber(contractNumber);
                    contractProcess.setSupplier_role_supplierID(supplierID);
                    contractProcess.setTariff_CurrentTarif_role_tariffID(tariffID);
                    contractProcess.setMorada(morada);
                    contractProcess.setAction("insert");

                    if (contractProcess.process().equals("Insert success")) {
                        return true;
                    }
                }
            }
        } catch (PersistentException ex) {
            Logger.getLogger(FacebookAccountManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }

    /**
     * Updates the contract's tariif.
     * 
     * @param contractID The primary key of the contract
     * @param tariffID The primary key of the tariff
     * @return if success: true
     */
    @Override
    public Boolean updateContract(Integer contractID, Integer tariffID) {
        try {
            smartgrid.ContractCriteria crit = new ContractCriteria();
            crit.add(Restrictions.eq("ID", contractID));
            smartgrid.Contract contract = smartgrid.Contract.loadContractByCriteria(crit);

            smartgrid.TariffCriteria tariffCrit = new TariffCriteria();
            tariffCrit.add(Restrictions.eq("ID", tariffID));
            smartgrid.Tariff tariff = smartgrid.Tariff.loadTariffByCriteria(tariffCrit);

            if (tariff.getSupplier_Tariffs_role().getID() == contract.getSupplier_role().getID()) {
                contract.tariff_PreviusTariffs_role.add(contract.getTariff_CurrentTarif_role());
                contract.setTariff_CurrentTarif_role(tariff);
                contract.save();
            }

        } catch (PersistentException ex) {
            Logger.getLogger(ContractsManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }

    /**
     * adds one Contract of one supplier to one facebookAccount
     * 
     * @param facebookAccountUID Facebook UID
     * @param supplierID Supplier primary key
     * @param contractNumber Number of Contract 
     * @param contractNif NIF of registered contract
     * @return if success: true
     */
    @Override
    public void addContractToFacebookAccount(String facebookAccountUID, Integer supplierID, String contractNumber, String contractNif) throws InvalidContractNifException, InvalidContractNumberException, ContractAlreadyExistsException, FacebookAccountNotExistException {
        try {
            SupplierCriteria supCrit = new SupplierCriteria();
            supCrit.add(Restrictions.eq("ID", supplierID));
            Supplier supplier = Supplier.loadSupplierByCriteria(supCrit);

            FaceBookAccountCriteria faceCrit = new FaceBookAccountCriteria();
            faceCrit.add(Restrictions.eq("UId", facebookAccountUID));
            FaceBookAccount faceAccount = FaceBookAccount.loadFaceBookAccountByCriteria(faceCrit);

            if(faceAccount == null)
                throw new FacebookAccountNotExistException();
            
            ContractCriteria contCrit = new ContractCriteria();
            contCrit.add(Restrictions.eq("Number", contractNumber));
            Contract contract = Contract.loadContractByCriteria(contCrit);
            
            if (contract == null) {
                if (supplier.getName().toUpperCase().equals("EDP")) {
                    InitialContext initCtx;
                    try {
                        initCtx = new InitialContext();
                        EDPbeanLocal edp = (EDPbeanLocal) initCtx.lookup("java:global/SmartGridEA/EDPbean");
                        contract = edp.getContract(contractNumber, contractNif);
                        contract.save();
                    } catch (NamingException ex) {
                        Logger.getLogger(ContractsManager.class.getName()).log(Level.SEVERE, null, ex);
                    }
                } else if (supplier.getName().toUpperCase().equals("ENDESA")) {
                    InitialContext initCtx;
                    try {
                        initCtx = new InitialContext();
                        ENDESAbeanLocal endesa = (ENDESAbeanLocal) initCtx.lookup("java:global/SmartGridEA/ENDESAbean");
                        contract = endesa.getContract(contractNumber, contractNif);
                        contract.save();
                    } catch (NamingException ex) {
                        Logger.getLogger(ContractsManager.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                if (contract != null) {
                    System.out.println(contract.getClientNif());
                    if (contract.getClientNif().toUpperCase().equals(contractNif)) {
                        if (faceAccount.contract_role.contains(contract)) {
                            throw new ContractAlreadyExistsException();
                        }
                        faceAccount.contract_role.add(contract);
                        faceAccount.save();

                    } else {
                        throw new InvalidContractNifException();
                    }
                }
            } 
            else{
                faceAccount.contract_role.add(contract);
                faceAccount.save();
            }

        } catch (PersistentException ex) {
            Logger.getLogger(ContractsManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Removes one Contract from one Facebook Account
     * @param facebookUID Facebook UID
     * @param contractNumber Number of the Contract
     * @return If Success True
     */
    @Override
    public Boolean removeContractFromFacebookAccount(String facebookUID, String contractNumber) {
        try {
            FaceBookAccountCriteria facCriteria = new FaceBookAccountCriteria();
            facCriteria.add(Restrictions.eq("UId", facebookUID));
            FaceBookAccount facebook = FaceBookAccount.loadFaceBookAccountByCriteria(facCriteria);

            ContractCriteria conCriteria = new ContractCriteria();
            conCriteria.add(Restrictions.eq("Number", contractNumber));
            Contract contract = Contract.loadContractByCriteria(conCriteria);

            if (facebook != null && contract != null) {
                if (facebook.contract_role.contains(contract)) {
                    facebook.contract_role.remove(contract);
                    return facebook.save();
                }
            }
        } catch (PersistentException ex) {
            Logger.getLogger(ContractsManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }

    /**
     * Removes one Contract from one Facebook Account
     * @param facebookUID Facebook account primary key
     * @param contractNumber Contract primary key
     * @return If Success True
     */
    @Override
    public Boolean removeContractFromFacebookAccountByORMID(String facebookID, String contractID) {
        try {
            FaceBookAccountCriteria facCriteria = new FaceBookAccountCriteria();
            facCriteria.add(Restrictions.eq("ID", facebookID));
            FaceBookAccount facebook = FaceBookAccount.loadFaceBookAccountByCriteria(facCriteria);

            ContractCriteria conCriteria = new ContractCriteria();
            conCriteria.add(Restrictions.eq("ID", contractID));
            Contract contract = Contract.loadContractByCriteria(conCriteria);

            if (facebook != null && contract != null) {
                if (facebook.contract_role.contains(contract)) {
                    facebook.contract_role.remove(contract);
                    return facebook.save();
                }
            }
        } catch (PersistentException ex) {
            Logger.getLogger(ContractsManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }

    public static void main(String[] args) {
        try {
            ContractCriteria contCrit = new ContractCriteria();
            contCrit.add(Restrictions.eq("supplier_role.id", 3));
            contCrit.add(Restrictions.eq("Number", "12345678"));
            Contract contract = Contract.loadContractByCriteria(contCrit);

            System.out.println(contract.getClientName() + "\n" + contract.getNumber());
        } catch (PersistentException ex) {
            Logger.getLogger(ContractsManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
